Skip to content

Feature/letsplot compose integration#507

Merged
phodal merged 2 commits intomasterfrom
feature/letsplot-compose-integration
Dec 9, 2025
Merged

Feature/letsplot compose integration#507
phodal merged 2 commits intomasterfrom
feature/letsplot-compose-integration

Conversation

@phodal
Copy link
Owner

@phodal phodal commented Dec 9, 2025

Summary by CodeRabbit

New Features

  • Added PlotDSL for generating statistical charts from natural language descriptions
  • Introduced LetsPlot rendering support for creating visualizations on desktop and Android platforms
  • Added support for multiple chart types (scatter, line, bar, histogram, heatmap, and more)
  • Added configurable themes, dimensions, and customization options for plot generation
  • Introduced a CLI tool for generating charts from text descriptions

Tests

  • Added comprehensive test coverage for chart parsing and generation

✏️ Tip: You can customize this high-level summary in your review settings.

- Add Lets-Plot Compose dependencies (v3.0.1) for JVM Desktop and Android
- Create PlotDSL parser (ggplot2-inspired YAML/JSON format)
- Add expect/actual LetsPlotBlockRenderer for cross-platform rendering
  - JVM/Android: Full Lets-Plot Compose rendering
  - iOS/JS/WASM: Fallback to code display
- Create PlotDSLAgent sub-agent for LLM chart generation
- Add PlotDSLCli for CLI testing
- Add unit tests for PlotParser
- Add integration tests for LLM PlotDSL generation

Supported chart types: bar, line, scatter, histogram, boxplot, area, density
Supported themes: default, minimal, classic, dark, light, void
Copilot AI review requested due to automatic review settings December 9, 2025 05:19
@phodal phodal merged commit 77086ad into master Dec 9, 2025
4 of 5 checks passed
@coderabbitai
Copy link

coderabbitai bot commented Dec 9, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request introduces PlotDSLAgent, a new agent for generating PlotDSL chart code from natural language descriptions. It adds conditional agent registration in CodingAgent, extends the SubAgent base class with an isAvailable property, implements platform-specific LetsPlot renderers with fallback support, and provides a CLI tool for standalone chart generation via LLM.

Changes

Cohort / File(s) Summary
Agent Framework Extensions
mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/core/SubAgent.kt, mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/core/SubAgentManager.kt
Added isAvailable property to SubAgent base class (defaults to true) for platform-specific availability checks. Updated registerSubAgent to return Boolean and skip registration if agent is unavailable.
PlotDSL Agent Implementation
mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/subagent/PlotDSLAgent.kt, mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/CodingAgent.kt
Introduced PlotDSLAgent class with LLM-based code generation, retry logic, and validation. Integrated into CodingAgent with conditional registration based on platform availability. Includes PlotDSLContext input model, PlotDSLValidationResult, and declarative tool schema.
Plot Data Model
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/PlotData.kt, mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/PlotParser.kt
Defined serializable PlotConfig, PlotDataFrame, PlotValue, PlotGeom, PlotTheme, ColorScale, PlotAesthetics, PlotFacet, and PlotLayer types. Implemented PlotParser to convert YAML/JSON/inline formats into PlotConfig.
Cross-Platform LetsPlot Renderers
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/LetsPlotBlockRenderer.kt, mpp-ui/src/jvmMain/kotlin/cc/unitmesh/.../LetsPlotBlockRenderer.jvm.kt, mpp-ui/src/androidMain/kotlin/cc/unitmesh/.../LetsPlotBlockRenderer.android.kt, mpp-ui/src/iosMain/kotlin/cc/unitmesh/.../LetsPlotBlockRenderer.ios.kt, mpp-ui/src/jsMain/kotlin/cc/unitmesh/.../LetsPlotBlockRenderer.js.kt, mpp-ui/src/wasmJsMain/kotlin/cc/unitmesh/.../LetsPlotBlockRenderer.wasmJs.kt
Implemented composable LetsPlotBlockRenderer with platform-specific implementations: JVM/Android with full LetsPlot rendering, iOS/JS/WASM with code-display fallbacks. Includes figure construction, layer support, theming, and error handling.
Build Configuration & CLI
mpp-ui/build.gradle.kts, mpp-ui/src/jvmMain/kotlin/cc/unitmesh/server/cli/PlotDSLCli.kt
Added Lets-Plot Compose dependencies (kernel, canvas, compose artifacts) for desktop/Android. Created PlotDSLCli entrypoint to generate charts from CLI with LLM integration and configuration loading. Added runPlotDSLCli Gradle task.
Tests
mpp-ui/src/jvmTest/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/PlotParserTest.kt, mpp-ui/src/jvmTest/kotlin/cc/unitmesh/devins/ui/integration/PlotDSLGenerationIntegrationTest.kt
Added 15 test cases for PlotParser covering YAML/inline parsing, geometry types, themes, aesthetics, and dimensions. Implemented integration test suite for LLM-generated PlotDSL output validation.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CodingAgent
    participant PlotDSLAgent
    participant LLM as KoogLLMService
    participant PlotParser
    participant Renderer as Platform Renderer
    
    User->>CodingAgent: Initialize with tool request
    alt PlotDSLAgent.isAvailable == true
        CodingAgent->>PlotDSLAgent: Register as sub-agent
        Note over CodingAgent: Register in toolRegistry & subAgentManager
    else Platform unsupported
        CodingAgent-->>CodingAgent: Skip registration
    end
    
    User->>CodingAgent: Execute with PlotDSL request
    CodingAgent->>PlotDSLAgent: Execute with PlotDSLContext
    
    PlotDSLAgent->>PlotDSLAgent: validateInput(context)
    PlotDSLAgent->>LLM: Generate PlotDSL code (with prompt)
    
    loop Retry on validation failure (max 3 attempts)
        LLM-->>PlotDSLAgent: Generated code
        PlotDSLAgent->>PlotDSLAgent: validatePlotDSL()
        alt Validation fails
            PlotDSLAgent->>PlotDSLAgent: buildRetryPrompt(errors)
            PlotDSLAgent->>LLM: Regenerate with feedback
        else Validation passes
            break
            end
        end
    end
    
    PlotDSLAgent-->>CodingAgent: Return formatted output
    CodingAgent->>PlotParser: Parse code block into PlotConfig
    PlotParser-->>Renderer: Provide PlotConfig
    
    alt Platform supports LetsPlot (JVM/Android)
        Renderer->>Renderer: buildLetsPlotFigure(config)
        Renderer-->>User: Render interactive chart
    else Platform unavailable
        Renderer-->>User: Display code with fallback message
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45–60 minutes

Areas requiring extra attention:

  • PlotDSLAgent logic — Retry mechanism, validation rules, and prompt engineering; ensure error handling covers edge cases and LLM failures gracefully.
  • PlotParser implementation — Multiple format paths (YAML/JSON/inline); verify parsing resilience and correct type conversions for all geom/theme combinations.
  • Platform-specific renderers — JVM/Android implementations with full LetsPlot integration and complex figure construction; validate geom mappings, layer handling, and aesthetic application across platforms.
  • Integration with CodingAgent — Conditional registration and initialization flow; confirm isAvailable checks work correctly and don't break existing functionality.
  • Test coverage — PlotParserTest and integration tests validate parsing and LLM output; verify test assertions cover all supported chart types and edge cases.

Possibly related PRs

Poem

🐰 A rabbit sketches plots with AI's art,
From words to charts, a magical start,
LetsPlot blooms on desktop and phone,
While other platforms still show the code—
Each geom a carrot, each layer a load! 📊✨

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/letsplot-compose-integration

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 15a5690 and edb7af6.

📒 Files selected for processing (16)
  • mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/CodingAgent.kt (4 hunks)
  • mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/core/SubAgent.kt (1 hunks)
  • mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/core/SubAgentManager.kt (1 hunks)
  • mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/subagent/PlotDSLAgent.kt (1 hunks)
  • mpp-ui/build.gradle.kts (3 hunks)
  • mpp-ui/src/androidMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/LetsPlotBlockRenderer.android.kt (1 hunks)
  • mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/LetsPlotBlockRenderer.kt (1 hunks)
  • mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/PlotData.kt (1 hunks)
  • mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/PlotParser.kt (1 hunks)
  • mpp-ui/src/iosMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/LetsPlotBlockRenderer.ios.kt (1 hunks)
  • mpp-ui/src/jsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/LetsPlotBlockRenderer.js.kt (1 hunks)
  • mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/LetsPlotBlockRenderer.jvm.kt (1 hunks)
  • mpp-ui/src/jvmMain/kotlin/cc/unitmesh/server/cli/PlotDSLCli.kt (1 hunks)
  • mpp-ui/src/jvmTest/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/PlotParserTest.kt (1 hunks)
  • mpp-ui/src/jvmTest/kotlin/cc/unitmesh/devins/ui/integration/PlotDSLGenerationIntegrationTest.kt (1 hunks)
  • mpp-ui/src/wasmJsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/LetsPlotBlockRenderer.wasmJs.kt (1 hunks)

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR integrates Lets-Plot Compose for statistical data visualization across the multiplatform codebase, adding support for generating and rendering ggplot2-inspired charts from natural language descriptions.

Key changes:

  • Introduces PlotDSL, a YAML-based DSL for defining statistical plots that's optimized for LLM token efficiency
  • Implements PlotDSLAgent SubAgent that generates chart code from natural language using LLM with retry/self-correction
  • Provides full Lets-Plot Compose rendering on JVM Desktop and Android, with graceful fallback to code display on iOS/JS/WASM

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/PlotData.kt Defines data models (PlotConfig, PlotGeom, PlotTheme, etc.) for PlotDSL serialization
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/PlotParser.kt Implements parser for YAML/JSON PlotDSL with fallback to simple format
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/LetsPlotBlockRenderer.kt Defines expect/actual interface for cross-platform chart rendering
mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/LetsPlotBlockRenderer.jvm.kt JVM implementation using Lets-Plot Compose for full chart rendering
mpp-ui/src/androidMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/LetsPlotBlockRenderer.android.kt Android implementation using Lets-Plot Compose (nearly identical to JVM)
mpp-ui/src/wasmJsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/LetsPlotBlockRenderer.wasmJs.kt WASM fallback showing PlotDSL code instead of rendering
mpp-ui/src/jsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/LetsPlotBlockRenderer.js.kt JS fallback using HTML elements to display code
mpp-ui/src/iosMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/LetsPlotBlockRenderer.ios.kt iOS fallback showing PlotDSL code
mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/subagent/PlotDSLAgent.kt SubAgent that generates PlotDSL from natural language with validation and retry logic
mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/core/SubAgent.kt Adds isAvailable property for platform-specific SubAgent availability
mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/core/SubAgentManager.kt Updates registration to check isAvailable before registering SubAgents
mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/CodingAgent.kt Integrates PlotDSLAgent with conditional registration based on platform
mpp-ui/src/jvmMain/kotlin/cc/unitmesh/server/cli/PlotDSLCli.kt CLI tool for testing PlotDSL generation from command line
mpp-ui/build.gradle.kts Adds Lets-Plot Compose dependencies for JVM and Android platforms
mpp-ui/src/jvmTest/kotlin/cc/unitmesh/devins/ui/compose/sketch/letsplot/PlotParserTest.kt Comprehensive unit tests for PlotParser covering all formats
mpp-ui/src/jvmTest/kotlin/cc/unitmesh/devins/ui/integration/PlotDSLGenerationIntegrationTest.kt Integration tests for end-to-end LLM-based chart generation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +142 to +144
}

subAgentManager.registerSubAgent(plotDSLAgent)
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conditional registration logic is inconsistent. PlotDSLAgent is registered to toolRegistry only when isAvailable is true (lines 139-142), but then unconditionally registered to subAgentManager (line 144). This could lead to the SubAgent being available in the manager but not as a tool. Either both should be conditional, or the subAgentManager.registerSubAgent() call should handle the availability check internally (which it does based on the SubAgentManager.kt changes).

Suggested change
}
subAgentManager.registerSubAgent(plotDSLAgent)
subAgentManager.registerSubAgent(plotDSLAgent)
}

Copilot uses AI. Check for mistakes.
Comment on lines +256 to +260
implementation("org.jetbrains.lets-plot:lets-plot-kotlin-kernel:4.12.0")
implementation("org.jetbrains.lets-plot:lets-plot-common:4.8.1")
implementation("org.jetbrains.lets-plot:canvas:4.8.1")
implementation("org.jetbrains.lets-plot:plot-raster:4.8.1")
implementation("org.jetbrains.lets-plot:lets-plot-compose:3.0.1")
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same version mismatch issue: lets-plot-kotlin-kernel is at version 4.12.0 while other Lets-Plot dependencies are at 4.8.1. This is the same issue as in jvmMain dependencies. Ensure consistent versions across all Lets-Plot dependencies for both JVM and Android platforms.

Copilot uses AI. Check for mistakes.
Comment on lines +46 to +47
@SerialName("scatter")
SCATTER,
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The PlotGeom enum contains both POINT and SCATTER which are treated as identical in the parser (line 190 of PlotParser.kt maps both "point" and "scatter" to PlotGeom.POINT). Having both enum values is redundant and could cause confusion. Consider removing SCATTER and only keeping POINT, or document clearly why both are needed (e.g., for different serialization scenarios).

Suggested change
@SerialName("scatter")
SCATTER,

Copilot uses AI. Check for mistakes.
Comment on lines +190 to +218
private fun validatePlotDSL(code: String): PlotDSLValidationResult {
val errors = mutableListOf<String>()
val warnings = mutableListOf<String>()

// Check if code is empty
if (code.isBlank()) {
errors.add("Generated code is empty")
return PlotDSLValidationResult(false, errors, warnings)
}

// Check for required sections
val hasDataSection = code.contains("data:") || code.contains("\"data\"")
val hasGeomSection = code.contains("geom:") || code.contains("\"geom\"")

if (!hasDataSection) {
errors.add("Missing 'data' section - chart needs data to visualize")
}

if (!hasGeomSection) {
warnings.add("Missing 'geom' section - using default chart type")
}

// Check for valid YAML/JSON structure
val hasValidStructure = (code.contains("plot:") || code.startsWith("{") ||
code.contains("data:") || code.contains("title:"))

if (!hasValidStructure) {
errors.add("Invalid PlotDSL structure - should be YAML or JSON format")
}
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validation logic uses simple string matching (code.contains("data:")) which could produce false positives if these strings appear in comments, string literals, or field values. Consider using the PlotParser itself for validation (e.g., PlotParser.parse(code) != null) to ensure the code is actually parseable, rather than relying on string matching heuristics.

Copilot uses AI. Check for mistakes.
Comment on lines +115 to +261
private fun buildLetsPlotFigure(config: PlotConfig): Figure {
val data = config.data.toMap()
val aes = config.aes

// Start with base plot
var plot: Plot = letsPlot(data)

// Add geometry layer
plot = when (config.geom) {
PlotGeom.POINT, PlotGeom.SCATTER -> {
plot + geomPoint {
aes?.x?.let { x = it }
aes?.y?.let { y = it }
aes?.color?.let { color = it }
aes?.size?.let { size = it }
aes?.shape?.let { shape = it }
aes?.alpha?.let { alpha = it }
}
}
PlotGeom.LINE -> {
plot + geomLine {
aes?.x?.let { x = it }
aes?.y?.let { y = it }
aes?.color?.let { color = it }
aes?.group?.let { group = it }
}
}
PlotGeom.BAR -> {
plot + geomBar(stat = Stat.identity) {
aes?.x?.let { x = it }
aes?.y?.let { y = it }
aes?.fill?.let { fill = it }
aes?.color?.let { color = it }
}
}
PlotGeom.HISTOGRAM -> {
plot + geomHistogram {
aes?.x?.let { x = it }
aes?.fill?.let { fill = it }
aes?.color?.let { color = it }
}
}
PlotGeom.BOXPLOT -> {
plot + geomBoxplot {
aes?.x?.let { x = it }
aes?.y?.let { y = it }
aes?.fill?.let { fill = it }
aes?.color?.let { color = it }
}
}
PlotGeom.AREA -> {
plot + geomArea {
aes?.x?.let { x = it }
aes?.y?.let { y = it }
aes?.fill?.let { fill = it }
aes?.group?.let { group = it }
}
}
PlotGeom.DENSITY -> {
plot + geomDensity {
aes?.x?.let { x = it }
aes?.fill?.let { fill = it }
aes?.color?.let { color = it }
}
}
PlotGeom.HEATMAP -> {
plot + geomTile {
aes?.x?.let { x = it }
aes?.y?.let { y = it }
aes?.fill?.let { fill = it }
}
}
PlotGeom.PIE -> {
// Lets-Plot doesn't have native pie, use bar with coord_polar
plot + geomBar(stat = Stat.identity) {
aes?.x?.let { x = it }
aes?.y?.let { y = it }
aes?.fill?.let { fill = it }
}
}
}

// Add additional layers if present
config.layers?.forEach { layer ->
val layerData = layer.data?.toMap() ?: data
val layerAes = layer.aes ?: aes

plot = when (layer.geom) {
PlotGeom.POINT, PlotGeom.SCATTER -> {
plot + geomPoint(data = layerData) {
layerAes?.x?.let { x = it }
layerAes?.y?.let { y = it }
layerAes?.color?.let { color = it }
}
}
PlotGeom.LINE -> {
plot + geomLine(data = layerData) {
layerAes?.x?.let { x = it }
layerAes?.y?.let { y = it }
layerAes?.color?.let { color = it }
}
}
else -> plot
}
}

// Add title and labels
config.title?.let { plot = plot + ggtitle(it, config.subtitle) }
if (config.xLabel != null || config.yLabel != null) {
plot = plot + labs(x = config.xLabel, y = config.yLabel)
}

// Add theme
plot = plot + when (config.theme) {
PlotTheme.MINIMAL -> themeMinimal()
PlotTheme.CLASSIC -> themeClassic()
PlotTheme.DARK -> themeBW() // Closest to dark
PlotTheme.LIGHT -> themeLight()
PlotTheme.VOID -> themeVoid()
PlotTheme.DEFAULT -> themeGrey()
}

// Add size
val width = config.width ?: 400
val height = config.height ?: 300
plot = plot + ggsize(width, height)

// Add color scale if specified
config.colorScale?.let { scale ->
plot = when (scale.type) {
ColorScaleType.DISCRETE -> {
scale.colors?.let { colors ->
plot + scaleFillManual(values = colors)
} ?: plot
}
ColorScaleType.CONTINUOUS, ColorScaleType.GRADIENT -> {
if (scale.low != null && scale.high != null) {
plot + scaleFillGradient(low = scale.low, high = scale.high)
} else {
plot
}
}
}
}

return plot
}
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The buildLetsPlotFigure function is duplicated between JVM and Android implementations with only minor differences (default heights: 300 vs 250, default widths: 400 vs 350). Consider extracting this ~150 line function into a common module and parameterizing the platform-specific default values to reduce code duplication and maintenance burden.

Copilot uses AI. Check for mistakes.
Comment on lines +155 to +156
// Note: initializeWorkspace is already called in init block, no need to call again here
// The buildContext() will handle MCP tools initialization if needed
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The comment on line 155 is misleading. It states "initializeWorkspace is already called in init block, no need to call again here," but this comment describes removed code behavior rather than explaining why the code was removed or what the current approach is. Consider removing this comment or updating it to explain the current initialization strategy more clearly.

Suggested change
// Note: initializeWorkspace is already called in init block, no need to call again here
// The buildContext() will handle MCP tools initialization if needed
// Workspace initialization is performed asynchronously in the init block.
// MCP tools initialization is handled within buildContext if needed.

Copilot uses AI. Check for mistakes.
Comment on lines +190 to +194
implementation("org.jetbrains.lets-plot:lets-plot-common:4.8.1")
implementation("org.jetbrains.lets-plot:canvas:4.8.1")
implementation("org.jetbrains.lets-plot:plot-raster:4.8.1")
implementation("org.jetbrains.lets-plot:lets-plot-image-export:4.8.1")
implementation("org.jetbrains.lets-plot:lets-plot-compose:3.0.1")
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Version mismatch in Lets-Plot dependencies. The lets-plot-kotlin-kernel is at version 4.12.0 while lets-plot-common, canvas, and plot-raster are at version 4.8.1. Consider using consistent versions across all Lets-Plot dependencies to avoid potential compatibility issues. Check the official Lets-Plot Compose documentation for the correct version combinations.

Suggested change
implementation("org.jetbrains.lets-plot:lets-plot-common:4.8.1")
implementation("org.jetbrains.lets-plot:canvas:4.8.1")
implementation("org.jetbrains.lets-plot:plot-raster:4.8.1")
implementation("org.jetbrains.lets-plot:lets-plot-image-export:4.8.1")
implementation("org.jetbrains.lets-plot:lets-plot-compose:3.0.1")
implementation("org.jetbrains.lets-plot:lets-plot-common:4.12.0")
implementation("org.jetbrains.lets-plot:canvas:4.12.0")
implementation("org.jetbrains.lets-plot:plot-raster:4.12.0")
implementation("org.jetbrains.lets-plot:lets-plot-image-export:4.12.0")
implementation("org.jetbrains.lets-plot:lets-plot-compose:4.12.0")

Copilot uses AI. Check for mistakes.
Comment on lines +46 to +48
} catch (e: Exception) {
parseSimpleFormat(trimmed)
}
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error handling in the parse function silently falls back to parseSimpleFormat for all exceptions (line 46-47). This could mask genuine errors like network issues, out of memory, or corrupted data. Consider logging the exception or at least distinguishing between parsing failures (which should fallback) and other types of exceptions (which should be propagated or logged).

Copilot uses AI. Check for mistakes.

val yamlContent = configFile.readText()
val yaml = Yaml(configuration = com.charleskorn.kaml.YamlConfiguration(strictMode = false))
val config = yaml.decodeFromString(AutoDevConfig.serializer(), yamlContent)
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing import or definition of AutoDevConfig and LLMConfigEntry. These classes are used but not imported or defined in this file. They should either be imported from cc.unitmesh.server.cli.DocumentCli or extracted into a shared location to avoid duplication.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments